A computer program is typically written in a high level language and compiled into a low level language for execution. The high level language version is referred to as source code. The low level language may be a native code that is understood by a machine processor, or an interpretable language that is understood and executed by an interpreter. A compiler front end typically parses the source code and generates a corresponding intermediate language (IL) representation. The intermediate language representation may be referred to simply as the intermediate language (IL). An IL may include an instruction set referred to as a bytecode. A code generator may receive the IL as input and generate the native code or other low level language code for execution.
One type of compiler is a static compiler that includes both a front end compiler and a code generator. The front end parses and translates the program into an intermediate language. The code generator translates the intermediate language to a native code, storing the native code in a file prior to execution of the program. In one technique, a debugging or analysis plug-in to the compiler may insert instructions in the IL, so that the inserted instructions are included in the native language. The inserted instructions may be used for debugging, analyzing, or optimizing the program. Inserting instructions may take multiple passes over the IL, or repeated computation of offsets in branch instructions, as the offsets of target instructions change due to insertion of new instructions. Because this is done prior to execution of the program being compiled, the extra time to do this is usually acceptable.
One technique for compilation and execution employs just-in-time (JIT) compilation. In this technique, the IL may be saved on a computer disk or dynamically generated in memory, and the IL for each function may be retrieved when it is invoked by the executing program. A code generator translates the function IL immediately prior to executing the function and saves the native code in memory, so that it is available the next time the function is invoked. It is desirable that the operations that are performed during execution of the program are fast, in order to enhance the operation of the program.